﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Configuration;
using KC.DataAccess.MV;
using KC.ExtensionMethods;
using BLL = KC.Business.Web;
using Logger = KC.Logging.Logger;

public partial class Office : System.Web.UI.Page
{
	private DateTime started;
	public IP ip;
	public Session session;
	public Dictionary<string, string> values;
	public BLL.MV8.RequestType ReqType;
	public Activity act;
	protected MV8DataContext dc = new MV8DataContext(ConfigurationManager.ConnectionStrings["MV8"].ConnectionString);

	protected void Page_Init(object sender, EventArgs e)
	{
		try
		{
			started = DateTime.Now;
			this.Error += new EventHandler(Page_Error);

			// if (session == null && !string.IsNullOrEmpty(txtSID.Text)) session = (from s in dc.Sessions where s.ID == int.Parse(txtSID.Text) select s).First();

			ReqType = BLL.MV8.RequestType.Invalid;
			ReqType = BLL.MV8.DetectRequestType(Request.RawUrl, out values);
			DetectIp();
			if (session == null) InitSession();

			Logger.LogHistory(ip.ID, "Request", "Request type: " + ReqType);
		}
		catch { }


	}
	protected void Page_Error(object sender, EventArgs e)
	{
		try { Logger.LogError(Logger.Project.MV, Logger.ErrorLevel.Critical, "Unhandled exception caught in Office: \n" + Server.GetLastError().ToString()); }
		catch { }
	}
	protected void Page_Load(object sender, EventArgs e)
	{
		// Detect spammy IPs and block their asses
		string domain = "";
		if (Request.UrlReferrer != null)
			domain = Request.UrlReferrer.GetRootDomain();
		if (!string.IsNullOrEmpty(domain) && Request.UrlReferrer.AbsoluteUri.ToLower().Trim().EndsWith("/sitemap.html"))
		{
			ip.NumProblems++;
			Response.Write("Your IP has been flagged for possible spam. Referrer: " + Server.HtmlEncode(Request.UrlReferrer.AbsoluteUri.ToLower().Trim()) + "<br />Furthermore, " + Server.HtmlEncode(domain) + " has ben added to the blacklist.");
			var blacklists = from b in dc.Blacklists where b.domain.ToLower() == domain.ToLower() select b;
			if (blacklists.Count() == 0)
				dc.Blacklists.InsertOnSubmit(new Blacklist() { AttemptedUsages = 1, domain = domain });
			else blacklists.First().AttemptedUsages++;
			dc.SubmitChanges();
		}

		// Detect and handle spammy TLDs (Because I get SO much legit traffic from .ru referrers)
		if (!string.IsNullOrEmpty(domain) && domain.Trim().ToLower().Replace("/", "").Replace("\\", "").EndsWithAny(new string[] { "ru", "tk" }))
		{
			ip.NumProblems++;
			dc.SubmitChanges();
			var blacklists = from b in dc.Blacklists where b.domain.ToLower() == domain.ToLower() select b;
			if (blacklists.Count() == 0)
				dc.Blacklists.InsertOnSubmit(new Blacklist() { AttemptedUsages = 1, domain = domain });
			else blacklists.First().AttemptedUsages++;
			dc.SubmitChanges();
		}


		// Ban IPs with many problems
		if (ip.NumProblems >= 3)
		{
			Response.Clear();
			Response.Write("<div style=\"width: 100%; text-align: center; margin: 0 auto;\"><img src=\"images/picard-flip.jpg\" alt=\"fuck you, asshole\" /></div><br /><br />\r\n");
			Response.Write("<h1 style=\"text-align:center;\">Access denied for spam</h1><br /><br /><table style=\"width: 100%;\">\r\n");

			List<KC.DataAccess.MV.Session> sessions = ip.Sessions.OrderByDescending(s => s.ID).Take(500).ToList();
			for (int i = 0; i < 100 && i < ip.Sessions.Count(); i++)
			{
				foreach (Activity act in sessions[i].Activities.ToList())
					Response.Write("<tr><td>" + act.DateTime.ToString("MM/dd/yy HH:mm:ss") + "</td><td>" + act.Session.IP.Address + "</td><td>" + (act.Referrer ?? "&nbsp;") + "</td><td>" + act.Request + "</td></tr>\r\n");
			}
			Response.Write("</table>");
			Controls.Clear();
			Response.Flush();
			Response.End();
			this.Session.Abandon();

			return;
		}


		// Detect bad domain links and 301 redirect permanently to the proper canonical domain
		if (!Request.Url.AbsoluteUri.ToLower().Contains("www.kconnolly.net") && !Request.Url.AbsoluteUri.ToLower().Contains("http://localhost:"))
		{
			string ProperUrl = "http://www.kconnolly.net";
			string OldUrl = Request.Url.AbsoluteUri.TrimEnd(new char[] { '?', ' ', '\t' });
			if (!OldUrl.Contains("://")) OldUrl = "http://" + OldUrl;
			ProperUrl = OldUrl
				.Replace(Request.Url.Host, "www.kconnolly.net")
				.Replace(":" + Request.Url.Port.ToString(), "");
			Logger.LogHistory(session.IPID, "Issuing 301 Redirect from " + Request.Url.Host + " to " + ProperUrl, "");
			Response.RedirectPermanent(ProperUrl);
		}

		if (session != null)
			session.dEnded = DateTime.Now;

		// Find Post ID to put into Activity object
		int? PostID = null;
		if (ReqType == BLL.MV8.RequestType.Post && (values.ContainsKey("id"))) PostID = (int?)int.Parse(values["id"]);
		else if (values.ContainsKey("title"))
			try
			{
				PostID = (from p2 in dc.Posts
						  where p2.FriendlyName.ToLower() == values["title"].ToLower()
						  select p2).First().ID;
			}
			catch { PostID = null; }

		
		LogActivity(ReqType == BLL.MV8.RequestType.Post ? (int?)PostID : null);
	}
	public void LogActivity(int? PostID)
	{
		try
		{
			dc.SubmitChanges();
			act = new Activity();
			act.SID = session.ID;
			act.DateTime = DateTime.Now;
			if (PostID != null) act.PID = PostID;
			dc.Activities.InsertOnSubmit(act);
			act.Request = Request.RawUrl;
			act.Referrer = Request.UrlReferrer == null ? null : Request.UrlReferrer.AbsoluteUri;
			act.UserAgent = Request.UserAgent;
			dc.SubmitChanges();
		}
		catch (Exception ex)
		{
			Response.Write(ex.ToString());
			Logger.LogError(Logger.Project.MV, Logger.ErrorLevel.Error, ex.Message);
		}

	}
	private void DetectIp()
	{
		// Find any IP(s) matching this address
		var ips = from a in dc.IPs
				  where a.Address == Request.UserHostAddress
				  orderby a.LastAccess descending
				  select a;
		if (ips.Count() == 1) // Exactly one match; use it.
			ip = ips.First();
		else if (ips.Count() > 1)
		{ // Multiple matches; error out and use the most recent one.
			// TODO
			// Logger.Write("MV7","Duplicate IPs", "Multiple IPs detected with Address " + Request.UserHostAddress + "; using " + ips.First().ID.ToString(), Logger.Severity.Error);
			ip = ips.First();
			return;
		}
		if (ips.Count() == 0)
		{ // No matches; add a new one
			ip = new IP();
			ip.Address = Request.UserHostAddress;
			try { ip.Domain = Request.UserHostName; }
			catch { }
			ip.FirstAccess = DateTime.Now;
			ip.Hits = 0;
			ip.isSpider = KC.Business.Net.Tracking.Spiders.isSpider(Request.UserAgent, Request.UserHostAddress);
			dc.IPs.InsertOnSubmit(ip);
		}

		// Update IP
		ip.Hits++;
		ip.LastAccess = DateTime.Now;
		dc.SubmitChanges();

	}
	private void InitSession()
	{
		session = new Session();
		session.dStarted = DateTime.Now;
		session.dEnded = DateTime.Now;
		session.IPID = ip.ID;
		session.UID = null;
		dc.Sessions.InsertOnSubmit(session);
		dc.SubmitChanges();
	}

}